#ifndef TRAV_MAIN_HEADER
#define TRAV_MAIN_HEADER

#include<iostream>
#include<iomanip>
#include<time.h>
#include<cmath>
#include<algorithm>
#include<string>
#include<fstream>

using namespace std;

//#define VERBOSE
//#define SWAP
//#define START_HEUR

const int MAP_SIZE_X = 300;
const int MAP_SIZE_Y = 300;
const int CITY_NUM = 100;

const int PRINT_SIZE_X = 200;
const int PRINT_SIZE_Y = 100;
const int BAR_LENGTH = 45;

const int GENERATION_PRINT = 1000;
const int POP_SIZE = 150;
const int CHILD_SIZE = POP_SIZE;

const int GENERATIONS = 20000;

const int INSERT_CHANCE = 100; 
const int FAR_CHANCE = 50;
const int INSERT_CONTINUE = 40;
const int INSERT_CONTINUE_MAX = CITY_NUM/3; 
const int SWAP_CHANCE = 40; //or 30

const int SWAPMORE_CHANCE = 70;
const int SWAPMORE_MAX = CITY_NUM/8;  //or 10

class Coord
{
private:
	int x;
	int y;
public:
	Coord();
	Coord(int,int);
	double distance(Coord);
	bool operator==(const Coord&);

	int getX(){return x;};
	int getY(){return y;};
};

class Map
{
private:
	Coord coords[CITY_NUM];
	char city;
	int* closeHeur;

	int* closestHeurPath();
public:
	Map();
	~Map();
	void print();

	Coord* getCoords(){return coords;};
	Coord getCoord(int c){return coords[c];};
	int* getClosestHeurPath(){return closeHeur;};
};

class Individual
{
private:
	int genome[CITY_NUM];
	Map* map;
	double distance;
	double updateDistance();
public:
	Individual();
	Individual(Map*);
	Individual(Map*,Individual);
	int getGenome(int a){return genome[a];};
	bool operator<(const Individual &other)const{return this->distance < other.distance;};
	Individual swapGenome();
	Individual insertGenome();
	double getDistance(){return distance;};
};

class Population
{
private:
	Individual pop[POP_SIZE];
	int generation;
	Map* map;
	int best[CITY_NUM];
public:
	Population(Map*);
	Population(Map*,Population);
	void printStat();
	void nextGeneration(int);
};

#endif
